package org.xlp.expression;

import org.xlp.assertion.AssertUtils;
import org.xlp.fraction.BigFraction;
import org.xlp.fraction.IFraction;

import java.math.BigDecimal;
import java.math.BigInteger;

/**
 * Description: 表达式计算类
 * <br/>date: 2024/11/28 17:24
 *
 * @version 1.0
 * @author: xlp
 */
public class ExpressionEvaluator extends Number {
    private Number expressionValue;

    /**
     * 构造函数
     * @param expression 数学表达式如： 1 +2 +4 *5
     * @throws NullPointerException 假如参数为null或空，则抛出该异常
     * @throws ExpressionParseException 假如表达式不合法，则抛出该异常
     */
    public ExpressionEvaluator(String expression){
        this(ExpressionParserFactory.getExpressionParser(expression));
    }

    /**
     * 构造函数
     * @param expression 数学表达式如： 1 +2 +4 *5
     * @param checker
     * @throws NullPointerException 假如第一个参数为null或空，则抛出该异常
     * @throws ExpressionParseException 假如表达式不合法，则抛出该异常
     */
    public ExpressionEvaluator(String expression, BigIntegerChecker checker){
        this(ExpressionParserFactory.getExpressionParser(expression, checker));
    }

    /**
     * 构造函数
     * @param parser 解析器
     * @throws NullPointerException 假如第一个参数为null，则抛出该异常
     * @throws ExpressionParseException 假如表达式不合法，则抛出该异常
     */
    public ExpressionEvaluator(IExpressionParser parser){
        AssertUtils.isNotNull(parser, "parser parameter must be not null!");
        this.expressionValue = parser.parse();
    }

    @Override
    public int intValue() {
        return expressionValue.intValue();
    }

    @Override
    public long longValue() {
        return expressionValue.longValue();
    }

    @Override
    public float floatValue() {
        return expressionValue.floatValue();
    }

    @Override
    public double doubleValue() {
        return expressionValue.doubleValue();
    }

    /**
     * 当结果是分数是，分数转换成指定的精度的小数(只对结果是分数生效)
     *
     * @param accuracy 假如accuracy小于0，则重新设置为0
     * @return
     */
    public double doubleValue(int accuracy) {
        return bigDecimalValue(accuracy).doubleValue();
    }

    /**
     * 当结果是分数是，分数转换成指定的精度的小数BigDecimal(只对结果是分数生效)
     *
     * @param accuracy 假如accuracy小于0，则重新设置为0
     * @return
     */
    public BigDecimal bigDecimalValue(int accuracy) {
        accuracy = Math.max(accuracy, 0);
        if (expressionValue instanceof IFraction){
            return ((IFraction<?, ?>) expressionValue).decimalValue(accuracy);
        }
        if (expressionValue instanceof  BigDecimal) return (BigDecimal) expressionValue;
        return  new BigDecimal(expressionValue.toString());
    }

    public BigDecimal bigDecimalValue(){
        if (expressionValue instanceof  BigDecimal) return (BigDecimal) expressionValue;
        if (expressionValue instanceof IFraction){
            return ((IFraction<?, ?>) expressionValue).decimalValue();
        }
        return  new BigDecimal(expressionValue.toString());
    }

    public BigInteger bigIntegerValue(){
        if (expressionValue instanceof  BigDecimal){
            return ((BigDecimal) expressionValue).toBigInteger();
        }
        if (expressionValue instanceof IFraction){
            return ((IFraction<?, ?>) expressionValue).bigIntegerValue();
        }
        if (expressionValue instanceof BigInteger) return (BigInteger) expressionValue;
        return new BigInteger(String.valueOf(expressionValue.longValue()));
    }

    /**
     * 返回分数对象
     */
    @SuppressWarnings("all")
    public IFraction<?, ?> fractionValue(){
        if (expressionValue instanceof IFraction){
            return (IFraction) expressionValue;
        }
        return BigFraction.valueOf(bigDecimalValue());
    }

    @Override
    public String toString(){
        return expressionValue instanceof BigDecimal ?
                ((BigDecimal) expressionValue).toPlainString() : expressionValue.toString();
    }
}
